var Squill = {};

(function(s){
 	
 	var isFirstRun = true, isReloded, classLoader;
 		
 	
 	var ap = new org.apache.tools.ant.Project();
 	ap.addBuildListener(new org.apache.tools.ant.listener.Log4jListener());
 	
 	var compiler = javax.tools.ToolProvider.getSystemJavaCompiler();
	var manager = compiler.getStandardFileManager(null,null,null);
	var diagnostics = new javax.tools.DiagnosticCollector();
	
	
	
	var loadDatabaseTableClasses = function(){
		
		var loader = java.lang.ClassLoader.getSystemClassLoader();
		with(java.net.URLClassLoader([])['class'].getDeclaredMethod("addURL", java.net.URL)){
			setAccessible(true);
			invoke(loader, [new java.net.URL("file:" + $core.installPath + "/lib/ext/commons-logging-1.1.1.jar")]);
			invoke(loader, [new java.net.URL("file:" + $core.installPath + "/lib/ext/squill.jar")]);
			invoke(loader, [new java.net.URL("file:" + $core.installPath + "/squill-classes/")]);
		}
		
		classLoader = new org.apache.commons.jci.ReloadingClassLoader(loader);
		var listener = new org.apache.commons.jci.listeners.ReloadingListener();
		listener.addReloadNotificationListener(classLoader);
		var fam = new org.apache.commons.jci.monitor.FilesystemAlterationMonitor()

		fam.addListener(new java.io.File("./squill-classes/"), listener);
		fam.start();
		isFirstRun = false;
			
	}
	
	var toJsType = function(obj){
		
		var jsType;
		switch(obj["class"] + ""){
			case "class java.lang.Integer":
				jsType = parseInt(obj);	
			break;
			default:
				jsType = obj + "";
		}
		
		return jsType;
	}
	
	
 	
 	s.init = function(args){
 		isReloded = true;
 		
 		if(!(args && args.host && args.database &&  args.user && args.tables && args.tables.constructor == Array && args.tables.length > 0))
 			throw "Squill initialization error!";
 				  
 		
		with(new Packages.squill.mgen.SquillMappingsTask()){
	 		setDriver(args.driver || "com.mysql.jdbc.Driver");
			setUrl("jdbc:mysql://" +args.host + ((args.port) ? ":" + args.port : "") + "/" + args.database);
			setSchema(args.schema || "PUBLIC");
			setUser(args.user);
			setPassword(args.password || "");
			setProject(ap)
			setPackageName("squill");
			setOutputPath((args.sourceOutput || $core.installPath + "/squill") + "/src");
			init();
			execute();
 		}
		
		var units = manager.getJavaFileObjectsFromFiles(java.util.Arrays.asList(new java.io.File("./squill-src/example/test/").listFiles()));
		manager.setLocation(javax.tools.StandardLocation.CLASS_PATH, java.util.Arrays.asList(new java.io.File($core.installPath + "/lib/ext/squill.jar")));
		manager.setLocation(javax.tools.StandardLocation.CLASS_OUTPUT, java.util.Arrays.asList(new java.io.File("./squill-classes/")));
		
		compiler.getTask(null, manager, diagnostics, null, null, units).call();
		manager.close();
		
		
			
		if(isFirstRun)
			loadDatabaseTableClasses();
		else	
			java.lang.Thread.sleep(2000);
			
		isReloded = false;
		
		s.getTable = {};
		s.getObject = {};
		
		for each(var table in args.tables){
			var className = table.charAt(0).toUpperCase() + table.substr(1, table.length);
			s.getTable[table] = function(){
				while(isReloded){
					java.lang.Thread.sleep(10);
				}
				var tableClass;
				try{
					tableClass = classLoader.loadClass("example.test." + className + "Data$"  +  className + "Table").newInstance();
				} catch(e){
					tableClass = null;
				}
				return tableClass
			}
			s.getObject[table] = function(){
				while(isReloded){
					java.lang.Thread.sleep(10);
				}
				var dataClass;
				try{
					dataClass = classLoader.loadClass("example.test." + className + "Data").newInstance();
				} catch(e) {
					dataClass = null;	
				}
				return dataClass
			}
		}
		var dataSource;
		with(dataSource = new com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource())
		{
			setUser(args.user);
			setPassword(args.password);
			setServerName(args.host);
			setPort( args.port || 3306);
			setDatabaseName(args.database);
		}
		
		
		return new Packages.squill.Squill(dataSource);
	}
	
	s.toJsResult = function(list, keys){
		var size = list.size();
		if(size > 0){
			var returnArr = [];
			for(var i =0, n = size; i < n; i++){
				var row = list.get(i);
				if(row.v1){
					var obj = {};
					for(var j = 1, m = 11; j < m; j++){
						obj[(keys && keys[j - 1]) ? keys[j - 1] : "v" + j] = toJsType(row["v" + j]);
					}
					returnArr.push(obj);
				} else {
					returnArr.push(toJsType(row));
				}
			}
			return returnArr;
			
		} else {
			return [];
		}
		
	}
	
})(Squill);
